package cur.nature.framework.core.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import cur.nature.framework.core.log.LOG;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.Date;

public class JWTUtil {

    public static String password = "XX#$%()(#*!()!KL<><MQLMsNaQNtQJQK?N<:{LWPW";
    public static long expireSecond = 1800L;// 30分钟
    @Data
    public static class Result {
        public static int OK = 0; //0-校验通过
        public static int ERROR = 1; // 1-校验失败
        public static int EXPIRE = 2;//2-过期
        private int status = 1;// 状态 0-校验通过, 1-校验失败, 2-过期
        private String msg;// 消息
        private String data;// 数据
        private long expireSeconds;// 数据
    }
    //密码token
    public static String encodeToken(final String userId) {
        String token = encode(userId, password, expireSecond);
        return token;
    }

    public static String encodeToken(final String userId,final long expireSend) {
        String token = encode(userId, password, expireSecond);
        return token;
    }
    //密码refresh_token
    public static String encodeRefreshToken(final String userId) {
        String token = encode(userId, password, expireSecond*2);
        return token;
    }

    // 解密token
    public static Result decodeToken(final String token) {
        Result result = decode(token, password);
        return result;
    }

    // 加密
    public static String encode(final String data, final String password,final long expireSend) {
        final String token = JWT.create()
                .withIssuer("curious")
                .withExpiresAt(new Date(System.currentTimeMillis()+(expireSend*1000)))  //设置过期时间
//        .withAudience("user1") //设置接受方信息，一般时登录用户
                .withClaim("data", data)
                .sign(Algorithm.HMAC256(password));  //使用HMAC算法，111111作为密钥加密
        return token;
    }

    // 解密
    public static Result decode(final String token, final String password) {
        Result result = new Result();
        try{
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(password)).build();
            Claim claim = JWT.decode(token).getClaim("data");
            final String data = claim == null ? "" : claim.asString();
            result.setData(data);
            jwtVerifier.verify(token);
            result.setStatus(0);
            return result;
        }
        catch (TokenExpiredException ex) {
            LOG.warn("token已过期: ",ex);
            result.setStatus(2);
            result.setMsg("token已过期");
//            LocalDateTime expireTime = DateUtil.instantToDate(ex.getExpiredOn());
            String expireStr = ex.getExpiredOn().toString();
            final LocalDateTime expireTime = LocalDateTime.parse(expireStr.substring(0,expireStr.length()-1));
            long seconds = DateUtil.compareDateTime(expireTime, LocalDateTime.now());
            result.setExpireSeconds(seconds);
        }
        catch (JWTVerificationException ex) {
            LOG.warn("token校验异常: ",ex);
            result.setStatus(1);
            result.setMsg("token校验异常");
        }
        return result;
    }

    public static void main(String[] args) {
        String token = encodeToken("2");
//        String token ="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoiMyIsImlzcyI6ImN1cmlvdXMiLCJleHAiOjE2ODk1OTM4MDF9.mtCkt_lQ8w5FMqEJI48uKxdcl5fFcjqQ9cMCfgmz8K8";
        System.out.println("token : " + token);
        Result data = decodeToken(token);
        Integer aa = Integer.valueOf(data.getData());
        System.out.println(aa);
        // 过期
        if(data.getStatus() == Result.EXPIRE) {
            System.out.println(data.getExpireSeconds());
            System.out.println("过期: " + (data.getExpireSeconds()/(60*60)));
        }
    }
}
